#pragma once
#ifndef _fastbird_Transformation_header_included_
#define _fastbird_Transformation_header_included_

#include <Engine/Math/Mat33.h>
#include <Engine/Math/Mat44.h>
#include <Engine/Math/Vec3.h>
#include <Engine/Math/Plane3.h>

namespace fastbird
{
	class Plane;
	class Transformation
	{
	public:
		Transformation();
		~Transformation();

		void MakeIdentity ();
		void MakeUnitScale ();
		inline bool IsIdentity () const
		{
			return mIdentity;
		}
		inline bool IsRSMatrix () const
		{
			return mRSMatrix;
		}
		inline bool IsUniformScale () const
		{
			return mRSMatrix && mUniformScale;
		}

		void SetRotate (const Mat33& r);
		inline const Mat33& GetRotate () const
		{
			assert(mRSMatrix);
			return mMat;
		}
		void SetMatrix (const Mat33& mat);
		inline const Mat33& GetMatrix () const
		{
			return mMat;
		}
		void SetTranslate (const Vec3& t);
		inline const Vec3& GetTranslate () const
		{
			return mT;
		}
		void SetScale (const Vec3& s);
		inline const Vec3& GetScale () const
		{
			assert(mRSMatrix);
			return mS;
		}
		void SetUniformScale (float fScale);
		inline float GetUniformScale () const
		{
			assert(mRSMatrix && mUniformScale);
			return mS.x;
		}

		float GetNorm () const;
		Vec3 ApplyForward (const Vec3& p) const;
		void ApplyForward (int iQuantity, const Vec3* points,
        Vec3* output) const;

		// X = M^{-1}*(Y-T) where Y is the input and X is the output.
		Vec3 ApplyInverse (const Vec3& p) const;
		void ApplyInverse (int iQuantity, const Vec3* points,
	        Vec3* output) const;

		Vec3 InvertVector (const Vec3& v) const;

		Plane3 ApplyForward (const Plane3& p) const;

		void Product (const Transformation& a, const Transformation& b);
		
		void Inverse (Transformation& t);
		void GetHomogeneous (Mat44& hm) const;

		static const Transformation IDENTITY;

	private:
		Mat33 mMat;
		Vec3 mT;
		Vec3 mS;
		bool mIdentity, mRSMatrix, mUniformScale;;
	};
}

#endif //_fastbird_Transform_header_included_